﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

/// <summary>
/// ECS组管理器
/// </summary>
public class ECSGroupMgr
{
    private ECSWorldBase m_world;
    /// <summary>
    /// 不同哈希对应的ecs组
    /// </summary>
    public Dictionary<int,ECSGroup> allGroupDic=new Dictionary<int, ECSGroup>();
    public List<ECSGroup> allGroupList=new List<ECSGroup>();
    /// <summary>
    /// 不同ecs组对应的实体列表
    /// </summary>
    public Dictionary<ECSGroup,List<ECSEntityBase>> group2Entitydic=new Dictionary<ECSGroup, List<ECSEntityBase>>();
    /// <summary>
   /// 不同实体对应的ecs组
   /// </summary>
    public Dictionary<ECSEntityBase,List<ECSGroup>> entity2GroupDic=new Dictionary<ECSEntityBase, List<ECSGroup>>();

    private string[] thisFilter;//临时过滤
    private ECSGroup thisGroup;//临时组
    private ECSRecordSystemBase thisRecordSys;//临时ecs记录系统
    private ECSSystemtBase thisSys;//临时ecs系统
    //-----------stringArrayToInt写成下标加?
    public ECSGroupMgr(ECSWorldBase world)
    {
        this.m_world = world;//指定组管理器所在世界

        //查询世界所有的系统的过滤组是否已键入ecs组管理器
        for (int i = 0,j=world.m_systemList.Count; i < j; i++)
        { 
            thisSys = world.m_systemList[i];
            thisFilter = thisSys.Filter;
            if (thisFilter.Length == 0)//如果该系统没有过滤器，不确定执行哪些组件
            {
                continue;
            }

            int key = StringArrayToInt(thisFilter);
            if (allGroupDic.ContainsKey(key))//如果该系统的哈希标志位已在字典中
            {
                continue;
            }
            //如果组管理器中未加入此系统的组
            thisGroup=new ECSGroup(key,thisFilter,world);//new一个ecs组
            allGroupDic.Add(key,thisGroup);
            allGroupList.Add(thisGroup);
            group2Entitydic.Add(thisGroup,new List<ECSEntityBase>());
        }
        //查询世界所有的记录系统的过滤组是否已键入ecs组管理器
        for (int i = 0,j=world.recordList.Count; i < j; i++)
        {
            thisRecordSys = world.recordList[i];
            thisFilter = thisRecordSys.Filter;
            if (thisFilter.Length.Equals(0))
            {
                continue;
            }

            int key = StringArrayToInt(thisFilter);
            if (allGroupDic.ContainsKey(key))
            {
                continue;
            }
            //如果组管理器中未加入此记录系统的组
            thisGroup = new ECSGroup(key, thisFilter, world);//new一个ecs组
            allGroupDic.Add(key, thisGroup);
            allGroupList.Add(thisGroup);
            group2Entitydic.Add(thisGroup, new List<ECSEntityBase>());
        }
    }
    //------后期考虑更改，把标志位换成下标加---------------
    /// <summary>
    /// 添加组(若可以添加，那么把组对应的实体，实体对应的组也键入<遍历entity2GroupDic.Keys>)
    /// </summary>
    /// <param name="key"></param>
    /// <param name="TFilter"></param>
    /// <returns></returns>
    private bool AddGroup(int key, string[] TFilter)
    {
        if (TFilter==null||TFilter.Length.Equals(0))
        {
            Debug.LogError("添加ecs组失败，组件过滤器为空");
            return false;
        }

        if (allGroupDic.ContainsKey(key))
        {
            Debug.LogError("添加ecs组失败，该组已存在，key："+key);
            return false;
        }
        ECSGroup group=new ECSGroup(key,TFilter,m_world);
        allGroupDic.Add(key,group);
        allGroupList.Add(group);
        //取出所有的实体
        List<ECSEntityBase> listEntity=new List<ECSEntityBase>(entity2GroupDic.Keys);
        ECSEntityBase thisEntity;
        for (int i = 0,j=listEntity.Count; i < j; i++)
        {
            //取出实体
            thisEntity = listEntity[i];
            bool isContains = true;
            //询问实体是否包含全部的过滤器类型
            for (int k = 0,h=TFilter.Length; k < h; k++)
            {
                if (!thisEntity.GetExistCom(TFilter[i]))
                {
                    isContains = false;
                }
            }
            //如果实体是包含全部的过滤器类型,加入该组对应的实体列表中
            if (isContains)
            {
                listEntity.Add(thisEntity);
                entity2GroupDic[thisEntity].Add(group);
            }
        }
        group2Entitydic.Add(group,listEntity);
        return true;
    }
    /// <summary>
    /// 获取实体对应的ecs组
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public List<ECSGroup> GetEntity_Group(ECSEntityBase entity)
    {
        List<ECSGroup> groupNames=new List<ECSGroup>();
        ECSGroup go;
        bool isCer=true;
        string comName;
        for (int i = 0,j=allGroupList.Count; i < j; i++)
        {
            go = allGroupList[i];
            int[] filterCom = go.compoentHashs;
            for (int k = 0; k < filterCom.Length; k++)
            {
                if (!entity.GetExistCom(filterCom[i]))
                {
                    isCer = false;
                    break;
                }
            }

            if (isCer)
            {
                groupNames.Add(go);
            }
        }

        return groupNames;
    }
    //------后期考虑更改，把标志位换成下标加---------------
    /// <summary>
    /// 过滤实体
    /// </summary>
    /// <param name="key"></param>
    /// <param name="filters"></param>
    /// <returns></returns>
    public List<ECSEntityBase> GetEntityByFilter(int key, string[] filters)
    {
        ECSGroup go;
        if (allGroupDic.TryGetValue(key,out go))
        {
            
        }
        else
        {
            AddGroup(key, filters);
            allGroupDic.TryGetValue(key, out go);
        }

        List<ECSEntityBase> list;
        if (group2Entitydic.TryGetValue(go,out list))
        {
            if (list!=null)
            {
                return list;
            }
        }

        return null;
    }

    public List<ECSEntityBase> GetEntityByFilter(string[] filters)
    {
        int key = StringArrayToInt(filters);
        return GetEntityByFilter(key, filters);
    }
    /// <summary>
    /// 获取实体对应的组
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public ECSGroup[] GetGroupByEntity(ECSEntityBase entity)
    {
        List<ECSGroup> list;
        if (entity2GroupDic.TryGetValue(entity,out list))
        {
            if (list !=null)
            {
                return list.ToArray();
            }
        }

        return null;
    }
    //实体创建时(添加进实体对应的组，添加进组对应的实体)
    /// <summary>
    /// 实体创建时(添加进实体对应的组，添加进组对应的实体)
    /// </summary>
    /// <param name="entity"></param>
    public void OnEntityCreate(ECSEntityBase entity)
    {
        List<ECSGroup> newgroupList = GetEntity_Group(entity);
        //添加进实体对应的组
        if (entity2GroupDic.ContainsKey(entity))
        {
            entity2GroupDic.Add(entity,newgroupList);
        }
        else
        {
            entity2GroupDic[entity] = newgroupList;
        }
        //添加进组对应的实体
        for (int i = 0,j=newgroupList.Count; i < j; i++)
        {
            group2Entitydic[newgroupList[i]].Add(entity);
        }
    }
    //实体销毁时
    /// <summary>
    /// 实体销毁时（重置group2Entitydic,entity2GroupDic）
    /// </summary>
    /// <param name="entity"></param>
    public void OnEntityDestory(ECSEntityBase entity)
    {
        List<ECSGroup> list = entity2GroupDic[entity];
        //清除group2Entitydic中该实体包含的组的索引
        for (int i = 0,j=list.Count; i < j; i++)
        {
            try
            {
                group2Entitydic[list[i]].Remove(entity);
            }
            catch (Exception e)
            {
                Debug.LogError("销毁实体失败，组管理器，组对应的实体列表中未能搜查到该实体"+e.ToString());
            }
            
        }
        //清除entity2GroupDic中该实体
        try
        {
            entity2GroupDic.Remove(entity);
        }
        catch (Exception e)
        {
            Debug.LogError("销毁实体失败，组管理器，实体对应的组字典中未能搜查到该实体"+e.ToString());
        }
    }
    //实体组件更改时------为完善----------------
    //-------------------------------------
    //----------------------------------
    public void OnEntityComponentChange(ECSEntityBase entity, int compIndex, ECSCompoentBase comp)
    {
        List<ECSGroup> oldGoup;
        if (!entity2GroupDic.TryGetValue(entity,out oldGoup))
        {
            oldGoup = new List<ECSGroup>();
            entity2GroupDic.Add(entity, oldGoup);
        }
        //获取实体对应的ecs组
        List<ECSGroup> newGroupList = GetEntity_Group(entity);

        entity2GroupDic[entity] = newGroupList;

        for (int i = 0,j=newGroupList.Count; i < j; i++)
        {
            ECSGroup sys = newGroupList[i];
            if (!oldGoup.Contains(sys))
            {
                List<ECSEntityBase> list = group2Entitydic[sys];
                if (list==null)
                {
                    list=new List<ECSEntityBase>();
                }

                if (!list.Contains(entity))
                {
                    list.Add(entity);
                }
               
            }
        }

        for (int i = 0,j=oldGoup.Count; i < j; i++)
        {
            ECSGroup sys = oldGoup[i];
            if (!newGroupList.Contains(sys))
            {
                List<ECSEntityBase> list = group2Entitydic[sys];
                if (list==null)
                {
                    list=new List<ECSEntityBase>();
                }

                if (list.Contains(entity))
                {
                    list.Remove(entity);
                }
               
            }
        }

    }
 


    //一组组件类型名返回一个特定标志位
    public int StringArrayToInt(string[] filter)
    {
        return 0;
    }
}

